﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace WP7AppLifecycleServiceApp
{
    /// <summary>
    /// Class for the Application.
    /// </summary>
    public partial class App : Application, WP7AppLifecycleService.IWP7Application
    {
        #region Fields

        /// <summary>
        /// Holds the root frame of the Phone Application.
        /// </summary>
        private PhoneApplicationFrame rootFrame;

        /// <summary>
        /// Avoid double-initialization.
        /// </summary>
        private bool phoneApplicationInitialized = false;

        #endregion Fields

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="App"/> class.
        /// </summary>
        public App()
        {
            // Add WP7AppLifecycleService to applicationLifetimeObjects
            this.ApplicationLifetimeObjects.Add(WP7AppLifecycleService.WP7AppLifecycleApplicationService.Current);

            // Global handler for uncaught exceptions. 
            UnhandledException += this.Application_UnhandledException;

            // Show graphics profiling information while debugging.
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // Display the current frame rate counters.
                Application.Current.Host.Settings.EnableFrameRateCounter = true;
            }

            // Standard Silverlight initialization
            InitializeComponent();

            // Phone-specific initialization
            this.InitializePhoneApplication();
        }

        #endregion Constructor

        #region Events
        
        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion Events

        #region Properties

        /// <summary>
        /// Gets the root frame of the Phone Application as a convenient easy access to it from the library.
        /// </summary>
        /// <returns>The root frame of the Phone Application.</returns>
        /// <remarks>When set in interface implementations it must fire the PropertyChanged event.</remarks>
        public PhoneApplicationFrame RootFrame
        {
            get
            {
                return this.rootFrame;
            }

            private set
            {
                if (value != this.rootFrame)
                {
                    this.rootFrame = value;
                    this.NotifyPropertyChanged("RootFrame");
                }
            }
        }

        #endregion Properties

        #region NotifyPropertyChanged

        /// <summary>
        /// Notifies that property value changed.
        /// </summary>
        /// <param name="propertyName">The name of the property that changed.</param>
        protected void NotifyPropertyChanged(string propertyName)
        {
            System.Diagnostics.Debug.WriteLine("NotifyPropertyChanged of " + this.GetType().ToString() + "." + propertyName);
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (null != handler)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion NotifyPropertyChanged

        #region private event handlers
        
        /// <summary>
        /// Code to execute if a navigation fails.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">A <see cref="NavigationFailedEventArgs"/> instance with the event data.</param>
        private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // A navigation has failed; break into the debugger
                System.Diagnostics.Debugger.Break();
            }
        }

        /// <summary>
        /// Code to execute on Unhandled Exceptions.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">A <see cref="ApplicatoinUnhandledExceptionEventArgs"/> instance with the event data.</param>
        private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // An unhandled exception has occurred; break into the debugger
                System.Diagnostics.Debugger.Break();
            }
        }

        #endregion private event handlers

        #region Phone application initialization

        /// <summary>
        /// Do not add any additional code to this method
        /// </summary>
        private void InitializePhoneApplication()
        {
            if (!this.phoneApplicationInitialized)
            {
                // Create the frame but don't set it as RootVisual yet; this allows the splash
                // screen to remain active until the application is ready to render.
                this.RootFrame = new PhoneApplicationFrame();
                this.RootFrame.Navigated += this.CompleteInitializePhoneApplication;

                // Handle navigation failures
                this.RootFrame.NavigationFailed += this.RootFrame_NavigationFailed;

                // Ensure we don't initialize again
                this.phoneApplicationInitialized = true;
            }
        }

        /// <summary>
        /// Do not add any additional code to this method.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">A <see cref="NavigationEventArgs"/> instance with the event data.</param>
        private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
        {
            // Set the root visual to allow the application to render
            if (RootVisual != this.RootFrame)
            {
                RootVisual = this.RootFrame;
            }

            // Remove this handler since it is no longer needed
            this.RootFrame.Navigated -= this.CompleteInitializePhoneApplication;
        }

        #endregion Phone application initialization
    }
}